//
// Created by 33145 on 2023/6/1.
//

#include "tcp_buffer.h"
#include "../common/rocket.h"

#include <cstring>

namespace rocket {


  TCPBuffer::TCPBuffer(int size) : _size(size) {
    _buffer.resize(size);
  }

  int TCPBuffer::readAble() const {
    return _write_index - _read_index;
  }

  int TCPBuffer::writeAble() {
    return _buffer.size() - _write_index;
  }

  int TCPBuffer::readIndex() const {
    return _read_index;
  }

  int TCPBuffer::writeIndex() const {
    return _write_index;
  }

  int TCPBuffer::writeToBuffer(const char *buf, int size) {
    if (size > writeAble()) {
      resizeBuffer(1.5 * (_write_index + size));
    }
    memcpy(&_buffer[_write_index], buf, size);
    _write_index += size;
    return size;
  }

  int TCPBuffer::readFromBuffer(std::vector<char> &re, int size) {
    if (readAble() <= 0) {
      return 0;
    }
    int read_size = readAble() > size ? size :readAble();
    std::vector<char> tmp(read_size);
    memcpy(&tmp[0], &_buffer[_read_index], read_size);

    re.swap(tmp);
    _read_index += read_size;
    adjustBuffer();
    return read_size;
  }

  void TCPBuffer::resizeBuffer(int new_size) {
    std::vector<char> tmp(new_size);
    int count = std::min(new_size, readAble());
    memcpy(&tmp[0], &_buffer[_read_index], count);
    _buffer.swap(tmp);

    _write_index = count;
    _read_index = 0;
  }

  void TCPBuffer::adjustBuffer() {
    if (_read_index < int(_buffer.size() / 3)) {
      return;
    }
    std::vector<char> buffer(_buffer.size());
    int count = readAble();

    memcpy(&buffer[0], &_buffer[_read_index], count);
    _buffer.swap(buffer);
    _read_index = 0;
    _write_index = _read_index + count;

    // buffer.clear();
  }

  void TCPBuffer::moveReadIndex(int size) {
    size_t j = _read_index + size;
    if (j >= _buffer.size()) {
      LOG_ERROR("moveReadIndex error, invalid size %d, old_read_index %d, buffer size %d", size, _read_index, _buffer.size());
      return;
    }
    _read_index = j;
    adjustBuffer();
  }

  void TCPBuffer::moveWriteIndex(int size) {
    size_t j = _write_index + size;
    if (j >= _buffer.size()) {
      LOG_ERROR("moveWriteIndex error, invalid size %d, old_read_index %d, buffer size %d", size, _read_index, _buffer.size());
      return;
    }
    _write_index = j;
    adjustBuffer();
  }
}